class PriorityQueue {
  constructor(array = []) {
    this.array = array;
    this.size = this.array.length;
  }
  /**
   * 入队
   * @param key  入队元素
   */
  enQueue (key) {
    this.array[this.size] = key;
    this.upAdjust();
  }

  /**
   * 出队
   */
  deQueue () {
    if (this.size <= 0) {
      throw Error('the queue is empty !');
    }
    // 获取堆顶元素
    let head = [];
    // 最后一个移动到堆顶
    this.array[0] = this.array[--this.size];
    this.downAdjust();
    return head;
  }

  /**
   * 上浮调整
   */
  upAdjust () {
    let childIndex = this.size - 1;
    let parentIndex = (childIndex - 1) / 2;
    // temp 保存插入的叶子节点值，用于最后的赋值
    let temp = this.array[childIndex];
    while (childIndex > 0 && temp < this.array[parentIndex]) {
      // 无需真正交换，单向赋值即可
      this.array[childIndex] = this.array[parentIndex];
      childIndex = parentIndex;
      parentIndex = (parentIndex - 1) / 2;
    }
    this.array[childIndex] = temp;
  }
  /**
  * 下沉调整
  */
  downAdjust () {
    // temp 保存父节点值，用于最后的赋值
    let parentIndex = 0;
    let temp = this.array[parentIndex];
    let childIndex = 1;
    while (childIndex < this.size) {
      // 如果有右孩子，且右孩子小于左孩子的值，则定位到右孩子
      if (childIndex + 1 < this.size && this.array[childIndex + 1] < this.array[childIndex]) {
        childIndex++;
      }
      // 如果父节点小于任何一个孩子的值，直接跳出
      if (temp <= this.array[childIndex]) break;
      // 无需真正的交换单向赋值即可
      array[parentIndex] = this.array[childIndex];
      parentIndex = childIndex;
      childIndex = 2 * childIndex + 1;
    }
    array[parentIndex] = temp;
  }
}

let priorityQueue = new PriorityQueue();
priorityQueue.enQueue(3);
priorityQueue.enQueue(5);
priorityQueue.enQueue(10);
priorityQueue.enQueue(2);
priorityQueue.enQueue(7);